package osgi;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.adaptor.EclipseStarter;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

public class OSGITest {
	private String realPath;//服务器启动的时候设置该值
	
	public String getRealPath() {
		return realPath;
	}

	public void setRealPath(String realPath) {
		this.realPath = realPath;
	}
	
	private String getOsgiBundles() {
		// 要加载的bundles
		String osgiBundles_ = "org.eclipse.osgi_3.3.0.200704022148.jar@1:start,osgi-classloader_1.0.0.jar@2:start";
		
		osgiBundles_ = "osgi-classloader_1.0.0.jar@start,com.springsource.javax.servlet-2.5.0.jar@start,com.springsource.javax.el-1.0.0.jar@start,com.springsource.javax.servlet.jsp-2.1.0.jar@start,com.springsource.org.apache.commons.logging-1.1.1.jar@start,com.springsource.org.apache.commons.collections-3.2.1.jar@start";
		osgiBundles_ += ",com.springsource.org.apache.commons.beanutils-1.8.0.jar@start,com.springsource.org.apache.commons.lang-2.4.0.jar@start,com.springsource.org.apache.commons.io-1.4.0.jar@start,com.springsource.org.apache.commons.fileupload-1.2.0.jar@start,com.springsource.org.apache.commons.el-1.0.0.jar@start,org.apache.jasper_5.5.17.v200806031609.jar@start";
		osgiBundles_ += ",org.eclipse.equinox.common_3.3.0.200704022148.jar@start,org.eclipse.update.configurator_3.2.100.v20070322.jar@start,org.eclipse.osgi.services_3.1.100.200704022148.jar@start,org.eclipse.equinox.jsp.jasper_1.0.100.v20080427-0830.jar@start,org.eclipse.equinox.registry_3.3.0.v20070318.jar@start,org.eclipse.equinox.jsp.jasper.registry_1.0.0.v20080427-0830.jar@start,org.eclipse.equinox.http.registry_1.0.0.200704022148.jar@start,org.eclipse.equinox.http.servlet_1.0.0.200704022148.jar@start";
		osgiBundles_ += ",org.eclipse.equinox.http.servletbridge_1.0.0.200704022148.jar@start,json-simple-1.1.jar@start,bluesky-component-kindeditor_1.0.0.jar@start";
		
		osgiBundles_ = "org.eclipse.equinox.common_3.3.0.200704022148.jar@start,org.eclipse.update.configurator_3.2.100.v20070322.jar@start,org.eclipse.equinox.http.servletbridge_1.0.0.200704022148.jar@start,org.eclipse.equinox.http.registry_1.0.0.200704022148.jar@start";
		
		String osgiBundles = "";
		String[] osgiBundleArr = osgiBundles_.split(",");
		for(int i = 0;i<osgiBundleArr.length;i++) {
			String osgiBundle = osgiBundleArr[i];
			int startLevel = i + 1;
			osgiBundles += "," + osgiBundle.replace("@", "@" + startLevel + ":");
		}
		osgiBundles = osgiBundles.substring(1);
		System.out.println(osgiBundles);
		return osgiBundles;
	}

	public BundleContext run() {
		BundleContext bundleContext = null;
		try {
			
			String osgiBundles = this.getOsgiBundles();
			
			// ## 启动Equinox的配置 ##
			// 重要:缺省情况下，Equinox启动后马上shutdown，通过该参数配置Equinox启动后不关闭
			FrameworkProperties.setProperty("osgi.noShutdown", "true");

			// 重要：让Equinox不检查eclipse.product和eclipse.application配置
			FrameworkProperties.setProperty("eclipse.ignoreApp", "true");

			FrameworkProperties.setProperty("osgi.bundles.defaultStartLevel",
					"25");
			FrameworkProperties.setProperty("osgi.bundles", osgiBundles);

			// bundles所在路径
			System.out.println(realPath);
			String bundlePath = this.realPath + "/WEB-INF/eclipse/plugins";
			FrameworkProperties.setProperty("osgi.syspath", bundlePath);

			// 启动OSGi容器
			EclipseStarter.run(new String[] { "-configuration",
					"configuration", "-console" }, null);

			// 取得BundleContext
			bundleContext = EclipseStarter
					.getSystemBundleContext();
			if (bundleContext != null) {
				for (int i = 0; i < bundleContext.getBundles().length; i++) {
					Bundle bundle = bundleContext.getBundles()[i];

					// 通过反射将OSGi外部的ClassLoader对象设置到ClassLoaderBundle Bundle中
					// 这样，就可以在OSGi容器内部加载OSGi外部的资源了
					if (bundle.getSymbolicName().equalsIgnoreCase(
							"osgi-classloader")) {
						System.out.println("将应用的类加载器设置到OSGI中");
						Class clazz = bundle
								.loadClass("osgi.classloader.ClassLoaderService");
						Object obj = clazz.newInstance();
						Method method = clazz.getMethod("setClassLoader",
								ClassLoader.class);
						method.invoke(obj, this.getClass().getClassLoader());

					}
				}

			} else {
				System.out.println("bundleContext is null");
			}
			
			Object service = getOSGiService(bundleContext, "osgi.classloader.IClassLoaderService");
			
			//测试调用OSGI内的方法
			Class clazz = getBundleClass(bundleContext, "osgi-classloader", "osgi.classloader.ClassLoaderService");
			if(clazz != null) {
				Object obj = clazz.newInstance();
				Method methodTest = clazz.getMethod("invokeOSGI", Map.class);//无参数
				Map paraMap = new HashMap();
				paraMap.put("outPara", "test测试");
				Object ret = methodTest.invoke(obj, paraMap);
				System.out.println(((Map)ret).get("ret"));
			}

			while (true) {
				Thread.sleep(10000);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				EclipseStarter.shutdown();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return bundleContext;
	}
	
	/**
     * 从equinox容器中获取OSGi服务instance   还可以基于此进一步处理多服务接口实现的状况
     * 
     * @param serviceName 服务名称（完整接口类名）
     * 
     * @return Object 当找不到对应的服务时返回null
     */
    public static Object getOSGiService(BundleContext bundleContext, String serviceName){
        ServiceReference serviceRef = bundleContext.getServiceReference(serviceName);
        if(serviceRef == null)
            return null;
        return bundleContext.getService(serviceRef);
    }
    
    /**
     * 获取OSGi容器中插件的类
     */
    public static Class<?> getBundleClass(BundleContext bundleContext, String bundleName,String className) throws Exception{
        Bundle[] bundles = bundleContext.getBundles();
        for (int i = 0; i < bundles.length; i++) {
            if(bundleName.equalsIgnoreCase(bundles[i].getSymbolicName())){
                return bundles[i].loadClass(className);
            }
        }
		return null;
    }
	
	public static void main(String[] args) {
	
	}

}
